package com.eduplatform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.eduplatform.dto.ExamDTO;
import com.eduplatform.entity.Exam;
import com.eduplatform.entity.Paper;
import com.eduplatform.entity.School;
import com.eduplatform.entity.Subject;
import com.eduplatform.entity.User;
import com.eduplatform.mapper.ExamMapper;
import com.eduplatform.mapper.PaperMapper;
import com.eduplatform.mapper.SchoolMapper;
import com.eduplatform.mapper.SubjectMapper;
import com.eduplatform.mapper.UserMapper;
import com.eduplatform.service.ExamService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 考试Service实现类
 */
@Service
public class ExamServiceImpl extends ServiceImpl<ExamMapper, Exam> implements ExamService {

    @Autowired
    private PaperMapper paperMapper;

    @Autowired
    private SubjectMapper subjectMapper;

    @Autowired
    private SchoolMapper schoolMapper;

    @Autowired
    private UserMapper userMapper;

    @Override
    public IPage<ExamDTO> pageExams(int page, int size, Long subjectId, Integer educationLevel,
            Integer status, Long schoolId, String keyword) {
        Page<Exam> examPage = new Page<>(page, size);

        LambdaQueryWrapper<Exam> wrapper = new LambdaQueryWrapper<>();

        // 添加查询条件
        if (subjectId != null) {
            wrapper.eq(Exam::getSubjectId, subjectId);
        }

        if (educationLevel != null) {
            wrapper.eq(Exam::getEducationLevel, educationLevel);
        }

        if (status != null) {
            wrapper.eq(Exam::getStatus, status);
        }

        if (schoolId != null) {
            wrapper.eq(Exam::getSchoolId, schoolId);
        }

        if (StringUtils.hasText(keyword)) {
            wrapper.like(Exam::getTitle, keyword);
        }

        // 按开始时间降序排序
        wrapper.orderByDesc(Exam::getStartTime);

        // 执行分页查询
        IPage<Exam> result = page(examPage, wrapper);

        // 转换为DTO对象
        IPage<ExamDTO> dtoPage = result.convert(this::convertToDTO);

        // 批量查询试卷、学科、学校和创建人信息
        if (!dtoPage.getRecords().isEmpty()) {
            // 获取所有试卷ID、学科ID、学校ID和创建人ID
            List<Long> paperIds = dtoPage.getRecords().stream()
                    .map(ExamDTO::getPaperId)
                    .distinct()
                    .collect(Collectors.toList());

            List<Long> subjectIds = dtoPage.getRecords().stream()
                    .map(ExamDTO::getSubjectId)
                    .distinct()
                    .collect(Collectors.toList());

            List<Long> schoolIds = dtoPage.getRecords().stream()
                    .map(ExamDTO::getSchoolId)
                    .filter(id -> id != null)
                    .distinct()
                    .collect(Collectors.toList());

            List<Long> creatorIds = dtoPage.getRecords().stream()
                    .map(ExamDTO::getCreatorId)
                    .distinct()
                    .collect(Collectors.toList());

            // 批量查询试卷信息
            List<Paper> papers = paperMapper.selectBatchIds(paperIds);
            Map<Long, String> paperMap = papers.stream()
                    .collect(Collectors.toMap(Paper::getId, Paper::getTitle));

            // 批量查询学科信息
            List<Subject> subjects = subjectMapper.selectBatchIds(subjectIds);
            Map<Long, String> subjectMap = subjects.stream()
                    .collect(Collectors.toMap(Subject::getId, Subject::getName));

            // 批量查询学校信息
            Map<Long, String> schoolMap = new HashMap<>();
            if (!schoolIds.isEmpty()) {
                List<School> schools = schoolMapper.selectBatchIds(schoolIds);
                schoolMap = schools.stream()
                        .collect(Collectors.toMap(School::getId, School::getName));
            }

            // 批量查询创建人信息
            List<User> users = userMapper.selectBatchIds(creatorIds);
            Map<Long, String> userMap = users.stream()
                    .collect(Collectors.toMap(User::getId, User::getUsername));

            // 设置试卷标题、学科名称、学校名称和创建人姓名
            for (ExamDTO dto : dtoPage.getRecords()) {
                dto.setPaperTitle(paperMap.getOrDefault(dto.getPaperId(), ""));
                dto.setSubjectName(subjectMap.getOrDefault(dto.getSubjectId(), ""));
                if (dto.getSchoolId() != null) {
                    dto.setSchoolName(schoolMap.getOrDefault(dto.getSchoolId(), ""));
                }
                dto.setCreatorName(userMap.getOrDefault(dto.getCreatorId(), ""));
            }
        }

        return dtoPage;
    }

    @Override
    public ExamDTO getExamDetail(Long id) {
        Exam exam = getById(id);
        if (exam == null) {
            return null;
        }

        ExamDTO dto = convertToDTO(exam);

        // 查询试卷信息
        Paper paper = paperMapper.selectById(exam.getPaperId());
        if (paper != null) {
            dto.setPaperTitle(paper.getTitle());
        }

        // 查询学科信息
        Subject subject = subjectMapper.selectById(exam.getSubjectId());
        if (subject != null) {
            dto.setSubjectName(subject.getName());
        }

        // 查询学校信息
        if (exam.getSchoolId() != null) {
            School school = schoolMapper.selectById(exam.getSchoolId());
            if (school != null) {
                dto.setSchoolName(school.getName());
            }
        }

        // 查询创建人信息
        User user = userMapper.selectById(exam.getCreatorId());
        if (user != null) {
            dto.setCreatorName(user.getUsername());
        }

        return dto;
    }

    @Override
    @Transactional
    public boolean addExam(ExamDTO examDTO) {
        Exam exam = new Exam();
        BeanUtils.copyProperties(examDTO, exam);

        // 检查试卷是否存在并且已发布
        Paper paper = paperMapper.selectById(exam.getPaperId());
        if (paper == null || paper.getStatus() != 1) {
            return false;
        }

        // 设置考试时长
        exam.setDuration(paper.getDuration());

        // 设置考试状态
        LocalDateTime now = LocalDateTime.now();
        if (exam.getStartTime().isAfter(now)) {
            exam.setStatus(0); // 未开始
        } else if (exam.getEndTime().isBefore(now)) {
            exam.setStatus(2); // 已结束
        } else {
            exam.setStatus(1); // 进行中
        }

        // 设置创建时间和更新时间
        exam.setCreateTime(now);
        exam.setUpdateTime(now);

        return save(exam);
    }

    @Override
    @Transactional
    public boolean updateExam(ExamDTO examDTO) {
        Exam exam = getById(examDTO.getId());
        if (exam == null) {
            return false;
        }

        // 只有未开始的考试才能修改
        if (exam.getStatus() != 0) {
            return false;
        }

        BeanUtils.copyProperties(examDTO, exam);

        // 检查试卷是否存在并且已发布
        Paper paper = paperMapper.selectById(exam.getPaperId());
        if (paper == null || paper.getStatus() != 1) {
            return false;
        }

        // 设置考试时长
        exam.setDuration(paper.getDuration());

        // 设置考试状态
        LocalDateTime now = LocalDateTime.now();
        if (exam.getStartTime().isAfter(now)) {
            exam.setStatus(0); // 未开始
        } else if (exam.getEndTime().isBefore(now)) {
            exam.setStatus(2); // 已结束
        } else {
            exam.setStatus(1); // 进行中
        }

        // 更新时间
        exam.setUpdateTime(now);

        return updateById(exam);
    }

    @Override
    @Transactional
    public boolean deleteExam(Long id) {
        Exam exam = getById(id);
        if (exam == null) {
            return false;
        }

        // 只有未开始的考试才能删除
        if (exam.getStatus() != 0) {
            return false;
        }

        return removeById(id);
    }

    @Override
    @Scheduled(fixedRate = 60000) // 每分钟执行一次
    @Transactional
    public boolean updateExamStatus() {
        LocalDateTime now = LocalDateTime.now();

        // 更新未开始的考试为进行中
        LambdaQueryWrapper<Exam> startWrapper = new LambdaQueryWrapper<>();
        startWrapper.eq(Exam::getStatus, 0)
                .le(Exam::getStartTime, now)
                .gt(Exam::getEndTime, now);

        List<Exam> startExams = list(startWrapper);
        if (!startExams.isEmpty()) {
            for (Exam exam : startExams) {
                exam.setStatus(1);
                exam.setUpdateTime(now);
                updateById(exam);
            }
        }

        // 更新进行中的考试为已结束
        LambdaQueryWrapper<Exam> endWrapper = new LambdaQueryWrapper<>();
        endWrapper.eq(Exam::getStatus, 1)
                .le(Exam::getEndTime, now);

        List<Exam> endExams = list(endWrapper);
        if (!endExams.isEmpty()) {
            for (Exam exam : endExams) {
                exam.setStatus(2);
                exam.setUpdateTime(now);
                updateById(exam);
            }
        }

        return true;
    }

    /**
     * 将实体对象转换为DTO对象
     */
    private ExamDTO convertToDTO(Exam exam) {
        ExamDTO dto = new ExamDTO();
        BeanUtils.copyProperties(exam, dto);
        return dto;
    }
}